/*
 * Vertex.h
 *
 *  Created on: 26.5.2010
 *      Author: celebro
 */

#ifndef VERTEX_H_
#define VERTEX_H_

#include <cmath>
#include <iostream>

struct Vertex
{
	float x, y, z;

	Vertex() {}

	Vertex(float x, float y, float z)
	{
		this->x = x;
		this->y = y;
		this->z = z;
	}

	void print()
	{
		std::cout << x << " " << y << " " << z << std::endl;
	}

	Vertex operator+ (Vertex param)
	{
	  Vertex temp;
	  temp.x = x + param.x;
	  temp.y = y + param.y;
	  temp.z = z + param.z;
	  return (temp);
	}

	Vertex operator- (Vertex param)
	{
	  Vertex temp;
	  temp.x = x - param.x;
	  temp.y = y - param.y;
	  temp.z = z - param.z;
	  return (temp);
	}

	Vertex& operator= (const Vertex &param)
	{
	  x = param.x;
	  y = param.y;
	  z = param.z;
	  return *this;
	}

	Vertex operator* (float factor)
	{
		Vertex temp;
		temp.x = x * factor;
		temp.y = y * factor;
		temp.z = z * factor;
		return (temp);
	}

	Vertex operator* (Vertex param)
	{
		Vertex temp;
		temp.x = y*param.z - z*param.y;
		temp.y = z*param.x - x*param.z;
		temp.z = x*param.y - y*param.x;
		return (temp);
	}

	float operator^ (Vertex param)
	{
		return (x*param.x + y*param.y + z*param.z);
	}


	static inline void normalize(Vertex &a)
	{
		float len = sqrt(a.x*a.x + a.y*a.y + a.z*a.z);
		if (len != 0) {
			len = 1.0f/len;
			a.x *= len;
			a.y *= len;
			a.z *= len;
		}
	}

	static Vertex normal(Vertex &a, Vertex &b, Vertex &c)
	{
		Vertex vec1 = b-a;
		Vertex vec2 = c-a;
		Vertex n = vec1*vec2;
		normalize(n);
		return (n);
	}

	float distance_square (Vertex &v) {
		float d = (x - v.x)*(x - v.x) + (y - v.y)*(y - v.y);
		return d;
	}


//	static inline float dot(Vertex &a, Vertex &b)
//	{
//		return a.x*b.x + a.y*b.y + a.z*b.z;
//	}
//
//	/* c = a X b*/
//	static inline void cross(Vertex &a, Vertex &b, Vertex &dest)
//	{
//		dest.x = a.y*b.z - a.z*b.y;
//		dest.y = a.z*b.x - a.x*b.z;
//		dest.z = a.x*b.y - a.y*b.x;
//	}
//
//	static inline void add(Vertex &a, Vertex &b, Vertex &dest)
//	{
//		dest.x = a.x + b.x;
//		dest.y = a.y + b.y;
//		dest.z = a.z + b.z;
//	}
//
//	static inline void sub(Vertex &a, Vertex &b, Vertex &dest)
//	{
//		dest.x = a.x - b.x;
//		dest.y = a.y - b.y;
//		dest.z = a.z - b.z;
//	}

};

struct Vertex2D
{
	float x, y;

	Vertex2D() {}

	Vertex2D(float x, float y)
	{
		this->x = x;
		this->y = y;
	}

	void print()
	{
		std::cout << x << " " << y << std::endl;
	}

	Vertex2D operator+ (Vertex2D param)
	{
	  Vertex2D temp;
	  temp.x = x + param.x;
	  temp.y = y + param.y;
	  return (temp);
	}

	Vertex2D operator- (Vertex2D param)
	{
	  Vertex2D temp;
	  temp.x = x - param.x;
	  temp.y = y - param.y;
	  return (temp);
	}

	Vertex2D& operator= (const Vertex2D &param)
	{
	  x = param.x;
	  y = param.y;
	  return *this;
	}

	void set (float x, float y)
	{
		this->x = x;
		this->y = y;
	}
};

struct Face
{
	Vertex v1, v2, v3;
	Vertex2D tex1, tex2, tex3;
	Vertex n;
	float d;
};

#endif /* VERTEX_H_ */
